package htmlsoup

import (
	"bytes"
	"fmt"
	"strings"

	"code.google.com/awwwe-browser/data"
)

const (
	titleAttributeName        = "title"
	altAttributeName          = "alt"
	alignAttributeName        = "align"
	alignAttrubuteValueCenter = "center"
	alignAttrubuteValueRight  = "right"
	alignAttrubuteValueLeft   = "left"
)

// text handlers

func writeToBufferImageVoice(node *SoupNode, bfr *bytes.Buffer) {
	var att *nodeAttribute
	var side, desc string
	if !node.isVisible {
		return
	}
	if node.attributes.containsName(alignAttributeName) {
		att = node.attributes.get(alignAttributeName)
		side = att.value
		if side != alignAttrubuteValueCenter {
			side += " side"
		}
	} else {
		side = "right side"
	}
	if node.attributes.containsName(altAttributeName) {
		att = node.attributes.get(altAttributeName)
		desc = att.value
	} else if node.attributes.containsName(titleAttributeName) {
		att = node.attributes.get(titleAttributeName)
		desc = att.value
	}
	if len(desc) > 0 {
		var s string
		var bfr *bytes.Buffer
		bfr = bytes.NewBuffer(data.EmptyBytes)
		bfr.Write(data.NewLineBytes)
		s = fmt.Sprintf("At the %s of the article is an image described as, quote, %s, end quote", side, desc)
		bfr.WriteString(entityReferences.makeSpeakable(s))
		bfr.Write(data.NewLineBytes)
		bfr.WriteString(att.value)
	}
}

func writeToBufferAbbrVoice(node *SoupNode, bfr *bytes.Buffer) {
	var att *nodeAttribute
	var tempbfr *bytes.Buffer
	if !node.isVisible {
		return
	}
	att = nil
	if node.attributes.containsName("title") {
		att = node.attributes.get("title")
	}
	tempbfr = bytes.NewBuffer(data.EmptyBytes)
	if att != nil && len(att.value) > 0 {
		tempbfr.WriteString(entityReferences.makeSpeakable(att.value))
	}
	node.writeToBufferChildrenVoices(tempbfr)
	if tempbfr.Len() > 0 {
		if node.pauseBefore {
			bfr.Write(data.VXMLLongPauseBytes)
		}
		bfr.Write(tempbfr.Bytes())
	}
}

func writeToBufferAcronymVoice(node *SoupNode, bfr *bytes.Buffer) {
	var att *nodeAttribute
	var tempbfr *bytes.Buffer
	if !node.isVisible {
		return
	}
	att = nil
	if node.attributes.containsName("title") {
		att = node.attributes.get("title")
	}
	tempbfr = bytes.NewBuffer(data.EmptyBytes)
	if att != nil && len(att.value) > 0 {
		tempbfr.WriteString(entityReferences.makeSpeakable(att.value))
	}
	node.writeToBufferChildrenVoices(tempbfr)
	if tempbfr.Len() > 0 {
		if node.pauseBefore {
			bfr.Write(data.VXMLLongPauseBytes)
		}
		bfr.Write(tempbfr.Bytes())
	}
}

func writeToBufferLabelVoice(node *SoupNode, bfr *bytes.Buffer) {
	// find the encapsulating form tag
	var n, parent, child *SoupNode
	var children *SliceSoupNode
	var i, length int
	var ss data.SliceString
	var temp *bytes.Buffer
	var sorted []string
	var bb []byte
	if !node.isVisible {
		return
	}
	ss = data.BuildSliceString(0, 5)
	temp = bytes.NewBuffer(data.EmptyBytes)
	n = node.parent
	// get the fieldset legends in reverse order.
	for {
		if n == nil {
			break
		} else if n.name == "fieldset" {
			// now find the legend
			children = &n.children
			length = children.Len()
			for i = 0; i < length; i++ {
				child = children.AtIndex(i)
				if child.name == "legend" {
					// get the legends text
					temp.Reset()
					child.voiceHandler(child, temp)
					bb = bytes.Trim(temp.Bytes(), data.WhiteSpaceString)
					temp.Reset()
					temp.Write(bb)
					ss.Append(temp.String())
					break
				}
			}
		}
		n = parent
	}
	// reverse the legends
	ss.Reverse()
	// now write this label's text
	children = &node.children
	length = children.Len()
	for i = 0; i < length; i++ {
		child = children.AtIndex(i)
		if child.nodeType == nodeTypeText {
			// get the text
			bfr.Write(data.SpaceBytes)
			temp.Reset()
			child.voiceHandler(child, temp)
			bb = bytes.Trim(temp.Bytes(), data.WhiteSpaceString)
			temp.Reset()
			temp.Write(bb)
			ss.Append(temp.String())
			break
		}
	}
	// join the legends and label
	sorted = ss.Slice()
	bfr.WriteString(strings.Join(sorted, ", "))
}

func writeToBufferAltTitleDescriptionVoice(node *SoupNode, bfr *bytes.Buffer) {
	var att *nodeAttribute
	var tempbfr *bytes.Buffer
	if !node.isVisible {
		return
	}
	att = nil
	if node.attributes.containsName("alt") {
		att = node.attributes.get("alt")
	}
	if att == nil || len(att.value) == 0 {
		if node.attributes.containsName("title") {
			att = node.attributes.get("title")
		}
	}
	if len(att.value) > 0 {
		tempbfr = bytes.NewBuffer(data.EmptyBytes)
		tempbfr.WriteString(entityReferences.makeSpeakable(att.value))
		node.writeToBufferChildrenVoices(tempbfr)
		if tempbfr.Len() > 0 {
			if node.pauseBefore {
				bfr.Write(data.VXMLLongPauseBytes)
			}
			bfr.Write(tempbfr.Bytes())
		}
	}
}

func writeToBufferValueVoice(node *SoupNode, bfr *bytes.Buffer) {
	var tempbfr *bytes.Buffer
	if !node.isVisible {
		return
	}
	tempbfr = bytes.NewBuffer(data.EmptyBytes)
	tempbfr.WriteString(entityReferences.makeSpeakable(node.value))
	node.writeToBufferChildrenVoices(tempbfr)
	if tempbfr.Len() > 0 {
		if node.pauseBefore {
			bfr.Write(data.VXMLLongPauseBytes)
		}
		bfr.Write(tempbfr.Bytes())
	}
}

func writeToBufferNoVoice(node *SoupNode, bfr *bytes.Buffer) {
	if !node.isVisible {
		return
	}
	tempbfr := bytes.NewBuffer(data.EmptyBytes)
	node.writeToBufferChildrenVoices(tempbfr)
	if tempbfr.Len() > 0 {
		if node.pauseBefore {
			bfr.Write(data.VXMLLongPauseBytes)
		}
		bfr.Write(tempbfr.Bytes())
	}
}

func (this *SoupNode) writeToBufferChildrenVoices(bfr *bytes.Buffer) {
	children := this.children
	length := children.Len()
	for i := 0; i < length; i++ {
		child := children.AtIndex(i)
		child.voiceHandler(child, bfr)
	}
}
